Retrieve the latest kindest/node image for tests#1120
Conversation
There was a problem hiding this comment.
Pull request overview
Updates the CI workflow to determine the latest Kubernetes version used for tests by querying Docker Hub for the newest kindest/node image tag, and emits a warning when kind images lag behind upstream Kubernetes releases.
Changes:
- Resolve
latesttest version from Docker Hubkindest/nodetags rather than GitHub Kubernetes releases. - Add a warning when the latest kind image minor version is behind the upstream Kubernetes latest minor.
- Simplify kind cluster creation to always use
kindest/node:${k8s_version}.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| k8s_version=$(curl -s "https://hub.docker.com/v2/repositories/kindest/node/tags?page_size=100&ordering=last_updated" \ | ||
| | grep -oE '"name":"v[0-9]+\.[0-9]+\.[0-9]+"' \ | ||
| | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' \ | ||
| | sort -V | tail -1) |
There was a problem hiding this comment.
The Docker Hub request only fetches the first page (page_size=100) ordered by last_updated, then picks the highest semver from that subset. If the highest kindest/node tag isn’t in the most-recently-updated 100 tags, this can resolve to an older Kubernetes version. Consider paginating until exhaustion (following the next link) or using an API query that guarantees you’re considering all version tags (e.g., ordering by name and iterating pages) before selecting the max.
| k8s_version=$(curl -s "https://hub.docker.com/v2/repositories/kindest/node/tags?page_size=100&ordering=last_updated" \ | |
| | grep -oE '"name":"v[0-9]+\.[0-9]+\.[0-9]+"' \ | |
| | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' \ | |
| | sort -V | tail -1) | |
| url="https://hub.docker.com/v2/repositories/kindest/node/tags?page_size=100&ordering=last_updated" | |
| all_tags="" | |
| while [ -n "$url" ]; do | |
| response=$(curl -s "$url") | |
| # Collect all semver tags from this page | |
| page_tags=$(printf '%s\n' "$response" \ | |
| | grep -oE '"name":"v[0-9]+\.[0-9]+\.[0-9]+"' \ | |
| | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+') | |
| if [ -n "$page_tags" ]; then | |
| all_tags="${all_tags}"$'\n'"${page_tags}" | |
| fi | |
| # Follow pagination via the "next" field; it is either a URL or null | |
| next_url=$(printf '%s\n' "$response" | grep -oE '"next":[^,]*' | sed -E 's/"next":(null|"([^"]*)")/\2/') | |
| if [ -z "$next_url" ]; then | |
| url="" | |
| else | |
| url="$next_url" | |
| fi | |
| done | |
| k8s_version=$(printf '%s\n' "$all_tags" | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+' | sort -V | tail -1) |
| k8s_version=$(curl -s "https://hub.docker.com/v2/repositories/kindest/node/tags?page_size=100&ordering=last_updated" \ | ||
| | grep -oE '"name":"v[0-9]+\.[0-9]+\.[0-9]+"' \ | ||
| | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' \ | ||
| | sort -V | tail -1) | ||
| echo "Resolved latest kindest/node version to: $k8s_version" | ||
|
|
||
| # Warn if kind's latest minor version lags behind the latest upstream Kubernetes minor version | ||
| k8s_latest=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/kubernetes/kubernetes/releases/latest \ | ||
| | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+') |
There was a problem hiding this comment.
curl -s will succeed even on HTTP errors, and if the grep/sort pipeline finds no matching tags, k8s_version becomes empty. That will later cause kind create cluster --image kindest/node: to fail with a confusing error (and the minor-version comparison may emit “integer expression expected”). Consider using curl -fsSL (and/or retries) and explicitly validating that k8s_version and k8s_latest are non-empty before continuing; otherwise exit 1 with a clear message.
| k8s_version=$(curl -s "https://hub.docker.com/v2/repositories/kindest/node/tags?page_size=100&ordering=last_updated" \ | |
| | grep -oE '"name":"v[0-9]+\.[0-9]+\.[0-9]+"' \ | |
| | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' \ | |
| | sort -V | tail -1) | |
| echo "Resolved latest kindest/node version to: $k8s_version" | |
| # Warn if kind's latest minor version lags behind the latest upstream Kubernetes minor version | |
| k8s_latest=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/kubernetes/kubernetes/releases/latest \ | |
| | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+') | |
| k8s_version=$(curl -fsSL "https://hub.docker.com/v2/repositories/kindest/node/tags?page_size=100&ordering=last_updated" \ | |
| | grep -oE '"name":"v[0-9]+\.[0-9]+\.[0-9]+"' \ | |
| | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' \ | |
| | sort -V | tail -1) | |
| if [ -z "$k8s_version" ]; then | |
| echo "::error::Failed to resolve latest kindest/node version from Docker Hub." | |
| exit 1 | |
| fi | |
| echo "Resolved latest kindest/node version to: $k8s_version" | |
| # Warn if kind's latest minor version lags behind the latest upstream Kubernetes minor version | |
| k8s_latest=$(curl -fsSL -o /dev/null -w '%{url_effective}' https://github.com/kubernetes/kubernetes/releases/latest \ | |
| | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+') | |
| if [ -z "$k8s_latest" ]; then | |
| echo "::error::Failed to resolve latest upstream Kubernetes version from GitHub releases." | |
| exit 1 | |
| fi |
| | grep -oE '"name":"v[0-9]+\.[0-9]+\.[0-9]+"' \ | ||
| | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' \ |
There was a problem hiding this comment.
The Docker Hub response is JSON, but it’s being parsed with grep. This is brittle (formatting/escaping changes can break it) and can accidentally match unrelated "name" fields. Prefer parsing the JSON with a proper tool available on GitHub-hosted runners (e.g., jq -r '.results[].name' or a small python -c JSON parser) and then apply the semver selection on those values.
| | grep -oE '"name":"v[0-9]+\.[0-9]+\.[0-9]+"' \ | |
| | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' \ | |
| | jq -r '.results[].name' \ | |
| | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \ |
| echo "k8s_version=$k8s_version" >> $GITHUB_ENV | ||
| - name: Create Kind Cluster(k8s version ${{ env.k8s_version }}) | ||
| echo "k8s_version=${k8s_version}" >> $GITHUB_ENV | ||
| - name: Create Kind Cluster (k8s version ${{ env.k8s_version }}) |
There was a problem hiding this comment.
${{ env.k8s_version }} in the step name won’t be populated by values written to $GITHUB_ENV at runtime (those affect the shell environment, not the expression env context). If you want the resolved version in the step name, emit it as a step output and reference steps.resolve-k8s-version.outputs..., or keep the name static and just echo the chosen version in the step logs.
| - name: Create Kind Cluster (k8s version ${{ env.k8s_version }}) | |
| echo "k8s_version=${k8s_version}" >> "$GITHUB_OUTPUT" | |
| - name: Create Kind Cluster (k8s version ${{ steps.resolve-k8s-version.outputs.k8s_version }}) |
After talking with Release team of K8s they told me that they do not always create images for every version of k8s. In this PR we are changing our logic to retrieve the latest publish image of kindest/node from docker hub itself. As part of the change we are also adding a warning, because now these 2 versions are decoupled, whenever a new minor of k8s is released and they do not publish a new kindest/node image, we write a warning in the output. Signed-off-by: Joao Pereira <joaopapereira@gmail.com>
d34f98b to
e8f7b71
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
What this PR does / why we need it:
After talking with Release team of K8s they told me that they do not always create images for every version of k8s. In this PR we are changing our logic to retrieve the latest publish image of kindest/node from docker hub itself.
As part of the change we are also adding a warning, because now these 2 versions are decoupled, whenever a new minor of k8s is released and they do not publish a new kindest/node image, we write a warning in the output.
Does this PR introduce a user-facing change?
Additional Notes for your reviewer:
Review Checklist:
a link to that PR
change